package com.um.springboot.starter.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.FileSet;

import java.io.*;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

@Slf4j
public class FileUtil {

	/**
	 * 序列化一个对象到文件
	 * 
	 * @param path
	 * @param obj
	 */
	public static void writeObject(String path, Object obj) {
		try {
			File file = new File(path.substring(0, path.lastIndexOf("/")));
			if (!file.exists())
				file.mkdirs();
			OutputStream os = new FileOutputStream(path);
			ObjectOutputStream objectOutput = new ObjectOutputStream(os);
			objectOutput.writeObject(obj);
			objectOutput.close();
			os.close();
		} catch (Exception e) {
			log.error("", e);
		}
	}

	/**
	 * 反序列化一个对象到文件
	 * 
	 * @param path
	 */
	public static Object readObject(String path) {
		try {
			InputStream in = new FileInputStream(path);
			ObjectInputStream objectInput = new ObjectInputStream(in);
			Object obj = objectInput.readObject();
			objectInput.close();
			in.close();
			return obj;
		} catch (Exception e) {
			log.error("", e);
			return null;
		}
	}

	public static byte[] read(InputStream is) {
		ByteArrayOutputStream bos = null;

		try {
			bos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = -1;
			while ((len = is.read(buffer)) != -1) {
				bos.write(buffer,0,len);
			}

			return bos.toByteArray();
		} catch (IOException e) {
			log.error("", e);
		} finally {
			try {
				if (is != null) {
					is.close();
				}

				if (bos != null) {
					bos.close();
				}
			} catch (IOException e) {
				log.error("", e);
			}
		}

		return new byte[0];
	}

	/**
	 * 创建文件所在的文件夹
	 * 
	 * @param path
	 *            文件或文件夹路径
	 */
	public static void mkdirs(String path) {
		File file = new File(path.substring(0, path.lastIndexOf("/")));
		if (!file.exists())
			file.mkdirs();
	}

	/**
	 * 获得路径的目录名称
	 * @param path 全路径
	 * @return
	 */
	public static String getDirectoryName(String path) {
		return path.substring(path.lastIndexOf("/") + 1);
	}
	
	/**
	 * 获得文件名称
	 * @param path 文件全路径
	 * @return 文件名称
	 */
	public static String getFileName(String path){
		File file = new File(path);
		return file.getName();
	}

	/**
	 * 获得文件后缀名
	 * 
	 * @param path
	 * @return
	 */
	public static String getSuffixName(String path) {
		File file = new File(path);
		if (file.isFile()) {
			int index = path.lastIndexOf(".");
			return path.substring(index + 1);
		} else {
			return "temp";
		}
	}

	public static String getExtionsion(String path) {
		int index = path.lastIndexOf(".");
		if (index >= 0)
			return path.substring(index + 1);
		else
			return "";
	}

	/**
	 * 判断当前路径文件是否存在
	 * 
	 * @param path
	 * @return
	 */
	public static boolean exists(String path) {
		File file = new File(path);
		return file.exists();
	}

	/**
	 * 创建一个新目录
	 * 
	 * @param path
	 * @param folderName
	 * @return
	 */
	public static boolean createFolder(String path, String folderName) {
		File file = new File(path + "/" + folderName);
		if (file.exists() == true)
			return false;
		try {
			return file.mkdirs();
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 删除文件夹或文件
	 * 
	 * @param path
	 * @return
	 */
	public static boolean deleteFile(String path) {
		File file = new File(path);
		if (file.exists())
			return file.delete();
		else
			return false;
	}

	/**
	 * 删除目录下面指定后缀的文件
	 * 
	 * @param path
	 *            目录路径
	 * @param suffix
	 *            后缀数组
	 * @return
	 */
	public static boolean deleteFiles(String path, String[] suffix) {
		File file = new File(path);
		return deleteAllFiles(file, suffix);
	}

	/**
	 * 删除目录下面所有的文件及目录
	 * 
	 * @param file
	 * @param suffix
	 *            后缀数组
	 * @return
	 */
	public static boolean deleteAllFiles(File file, String[] suffix) {
		boolean success = true;
		if (file.isFile()) {
			String fileName = file.getName();
			for (int index = 0; index < suffix.length; index++) {
				String extenstion = getExtionsion(fileName);
				if (extenstion.toLowerCase().equals(suffix[index])) {
					file.delete();
					break;
				}
			}
		} else if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (File tempFile : files) {
				success = success && deleteAllFiles(tempFile, suffix);
			}
		}
		return success;
	}

	/**
	 * 删除目录
	 * 
	 * @param path
	 * @return
	 */
	public static boolean deleteDir(String path) {
		File file = new File(path);
		deleteAllFiles(file);
		return file.delete();
	}

	/**
	 * 删除目录下面所有的文件及目录
	 * 
	 * @param file
	 * @return
	 */
	public static boolean deleteAllFiles(File file) {
		boolean success = true;
		if (file.isFile())
			file.delete();
		else if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (File tempFile : files) {
				success = success && deleteAllFiles(tempFile);
			}
			success = success && file.delete();
		}
		return success;
	}

	/**
	 * 重命名
	 * 
	 * @param oldPath
	 * @param newPath
	 * @return
	 */
	public static boolean rename(String oldPath, String newPath) {
		File oldFile = new File(oldPath);
		File newFile = new File(newPath);
		boolean result = oldFile.renameTo(newFile);
		return result;
	}

	/**
	 * 获得跟径的所有文件
	 * 
	 * @param path
	 * @return
	 */
	public static String getFiles(String path) {
		StringBuilder sb = new StringBuilder();
		File file = new File(path);
		File[] files = file.listFiles();
		if (files == null || files.length == 0)
			return null;
		for (int index = 0; index < files.length; index++) {
			File tempFile = files[index];
			if (tempFile.isFile()) {
				sb.append(tempFile.getName() + ";");
			}
		}
		sb.delete(sb.length() - 1, sb.length());
		return sb.toString();
	}

	/**
	 * 创建文件夹
	 * 
	 * @param path
	 *            文件夹路径
	 * @throws Exception
	 */
	public static void mkdir(String path) throws Exception {
		File file = new File(path);
		file.mkdir();
	}

	/**
	 * 复制一个文件
	 * 
	 * @param source
	 *            源文件路径
	 * @param dest
	 *            目标文件路径
	 * @throws Exception
	 */
	public static void copyFile(String source, String dest) throws Exception {
		int bytesum = 0;
		int byteread = 0;
		File oldfile = new File(source);
		File newFile = new File(dest.substring(0, dest.lastIndexOf("/")));
		if (!newFile.exists())// 创建目录
			newFile.mkdirs();
		if (oldfile.exists()) { // 文件存在时
			InputStream inStream = new FileInputStream(source); // 读入原文件
			FileOutputStream fs = new FileOutputStream(dest);
			byte[] buffer = new byte[1024];
			while ((byteread = inStream.read(buffer)) != -1) {
				bytesum += byteread; // 字节数 文件大小
				fs.write(buffer, 0, byteread);
			}
			inStream.close();
			fs.close();
		}
	}

	/**
	 * 移动一个文件
	 * 
	 * @param source
	 *            源文件路径
	 * @param dest
	 *            目标文件路径
	 * @throws Exception
	 */
	public static void moveFile(String source, String dest) throws Exception {
		copyFile(source, dest);
		File file = new File(source);
		file.delete();
	}

	/**
	 * 复制文件夹内的所有文件
	 * 
	 * @param file
	 * @param dest
	 *            目标目录
	 * @throws Exception
	 */
	public static void copyAllFiles(File file, boolean root, String dest)
			throws Exception {
		if (file.isFile()) {
			copyFile(file.getPath(), dest + "/" + file.getName());
		} else if (file.isDirectory()) {
			if (!root)
				dest = dest + "/" + file.getName();
			File[] files = file.listFiles();
			for (File tempFile : files) {
				copyAllFiles(tempFile, false, dest);
			}
		}
	}

	/**
	 * 复制一个目录
	 * 
	 * @param source
	 *            源目录
	 * @param dest
	 *            目标目录
	 * @throws Exception
	 */
	public static void copyDir(String source, String dest) throws Exception {
		File file = new File(source);
		if (!file.exists())
			return;
		copyAllFiles(file, true, dest);
	}

	/**
	 * 移动一个目录
	 * 
	 * @param source
	 *            源目录
	 * @param dest
	 *            目标目录
	 * @throws Exception
	 */
	public static void moveDir(String source, String dest) throws Exception {
		File file = new File(source);
		if (!file.exists())
			return;
		copyAllFiles(file, true, dest);
		deleteAllFiles(file);
	}

	/**
	 * 获得当前目录下面的所有文件夹
	 * 
	 * @param path
	 * @return
	 */
	public static String getFolders(String path) {
		StringBuilder sb = new StringBuilder();
		File file = new File(path);
		File[] files = file.listFiles();
		if (files == null || files.length == 0)
			return null;
		for (int index = 0; index < files.length; index++) {
			File tempFile = files[index];
			if (tempFile.isDirectory()) {
				sb.append(tempFile.getName() + ";");
			}
		}
		sb.delete(sb.length() - 1, sb.length());
		return sb.toString();
	}

	/**
	 * 获得路径的所有目录和文件
	 * 
	 * @param path
	 * @return
	 */
	public static List<File> getFoldersAndFiles(String path) {
		File file = new File(path);
		File[] files = file.listFiles();
		if (files == null || files.length == 0)
			return null;
		List<File> lstFolder = new ArrayList<File>();

		for (int index = 0; index < files.length; index++) {
			File tempFile = files[index];
			lstFolder.add(tempFile);
		}
		return lstFolder;
	}

	public static String createFolderName(String path, String fileName) {
		File file = new File(path + "/" + fileName);
		if (!file.exists())
			return fileName;
		boolean success = false;
		int index = 2;
		while (success == false) {
			String tempName = fileName + "(" + index + ")";
			File f = new File(path + "/" + tempName);
			if (!f.exists())
				return tempName;
			index++;
		}
		return "";
	}

	public static String createFileName(String path, String fileName) {
		File file = new File(path + "/" + fileName);
		if (!file.exists())
			return fileName;
		boolean success = false;
		int index = 2;
		String name = fileName.substring(0, fileName.lastIndexOf(".") - 1);
		String suf = fileName.substring(fileName.lastIndexOf("."));
		while (success == false) {
			String tempName = name + "(" + index + ")" + suf;
			File f = new File(path + "/" + tempName);
			if (!f.exists())
				return tempName;
			index++;
		}
		return "";
	}

	/**
	 * 写文件字符串内容
	 * 
	 * @param path
	 *            文件路径
	 * @param fileName
	 *            文件名
	 * @param content
	 *            文件字符串内容
	 */
	public static void writeString(String path, String fileName, String content) {
		try {
			File file = new File(path);
			if (!file.exists())
				file.mkdirs();
			FileOutputStream os = new FileOutputStream(path + "/" + fileName);
			OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
			writer.write(content);
			writer.close();
			os.close();
		} catch (FileNotFoundException e) {
			log.error("", e);
		} catch (IOException ex) {
			log.error("", ex);
		}
	}
	
	/**
	 * 写文件字符串内容
	 * 
	 * @param path
	 *            文件路径
	 * @param fileName
	 *            文件名
	 * @param content
	 *            文件字符串内容
	 */
	public static void writeString(String path, String fileName, String content,String charset) {
		try {
			File file = new File(path);
			if (!file.exists())
				file.mkdirs();
			FileOutputStream os = new FileOutputStream(path + "/" + fileName);
			OutputStreamWriter writer = new OutputStreamWriter(os, charset);
			writer.write(content);
			writer.close();
			os.close();
		} catch (FileNotFoundException e) {
			log.error("", e);
		} catch (IOException ex) {
			log.error("", ex);
		}
	}

	/**
	 * 读文件字符串的内容
	 * 
	 * @param path
	 *            文件路径
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static String readString(String path, String fileName) {
		StringBuffer sb = new StringBuffer();
		try {
			File file = new File(path + "/" + fileName);
			if (!file.exists())
				return null;
			FileInputStream input = new FileInputStream(file);
			BufferedReader br = new BufferedReader(new InputStreamReader(input,"UTF-8"));
			String line = br.readLine();
			while (line != null) {
				sb.append(line);
				line = br.readLine();
			}
			br.close();
			input.close();
		} catch (FileNotFoundException e) {
			log.error("", e);
		} catch (IOException ex) {
			log.error("", ex);
		}
		return sb.toString();
	}

	/**
	 * 读文件字符串的内容
	 *
	 * @param path
	 *            文件路径
	 * @return
	 */
	public static String readString(String path) {
		StringBuffer sb = new StringBuffer();
		try {
			File file = new File(path);
			if (!file.exists())
				return null;
			FileInputStream input = new FileInputStream(file);
			BufferedReader br = new BufferedReader(new InputStreamReader(input,"UTF-8"));
			String line = br.readLine();
			while (line != null) {
				sb.append(line);
				line = br.readLine();
			}
			br.close();
			input.close();
		} catch (FileNotFoundException e) {
			log.error("", e);
		} catch (IOException ex) {
			log.error("", ex);
		}
		return sb.toString();
	}

	/**
	 * 读取XML文件的内容
	 * @param path XML文件路径
	 * @return 返回Map,键data为xml的内容，msg为读取文件的相关信息
	 */
	@SuppressWarnings("unchecked")
	public static Map readXMLFile(String path){
		Map mapResult = new Hashtable();
		StringBuffer sb = new StringBuffer();
		try {
			File file = new File(path);
			if (!file.exists()){
				mapResult.put("msg", FileUtil.getFileName(path)+"文件不存在！");
				return mapResult;
			}
			
			FileInputStream input = new FileInputStream(file);
			BufferedReader br = new BufferedReader(new InputStreamReader(input,"UTF-8"));
			String line = br.readLine();
			while (line != null) {
				sb.append(line);
				line = br.readLine();
			}
			br.close();
			input.close();
			mapResult.put("data", sb.toString());
		} catch (FileNotFoundException e) {
			log.error("", e);
			mapResult.put("msg", FileUtil.getFileName(path)+"文件不存在！");
		} catch (IOException ex) {
			log.error("", ex);
			mapResult.put("msg", FileUtil.getFileName(path)+"读取文件失败！");
		}
		return mapResult;
	}
	
	public static void saveImage(String path, InputStream is) {
		try {
			int len = 0;// 处理流

			int size = 0;
			byte[] tmp = new byte[100000];

			File f = new File(path);
			DataOutputStream dos = new DataOutputStream(new FileOutputStream(f));
			while ((len = is.read(tmp)) != -1) {
				dos.write(tmp, 0, len);
				size += len;
			}
			dos.flush();
			dos.close();
		} catch (IOException e) {
			log.error("", e);
		}

	}

	/**
	 * 压缩zip文件
	 * @param zipPathAndName 压缩zip的路径，包括文件名
	 * @param srcPathName 待压缩的zip文件夹全路径
	 * @param filter 忽略压缩的文件后缀 如:png,jpg
	 */
	public static void zip(String zipPathAndName, String srcPathName,String filter) {
		File zipFile = new File(zipPathAndName);
		if (filter != null)
			filter = "*." + filter;
		File srcdir = new File(srcPathName);
		if (!srcdir.exists())
			throw new RuntimeException(srcPathName + "不存在！");

		Project prj = new Project();
		Zip zip = new Zip();
		zip.setProject(prj);
		zip.setDestFile(zipFile);
		FileSet fileSet = new FileSet();
		fileSet.setProject(prj);
		fileSet.setDir(srcdir);
		// fileSet.setIncludes("**/*.java"); 包括哪些文件或文件夹
		// eg:zip.setIncludes("*.java");
		fileSet.setExcludes(filter); // 排除哪些文件或文件夹
		zip.addFileset(fileSet);

		zip.execute();
	}

	/**
	 * 解压zip或rar压缩文件
	 * @param sourceFile zip或rar文件名的全路径，包括文件名
     * @param destDir 需要压缩的文件夹的全路径
	 * @return 成功返回0，失败返回1
	 */
	public static int unzip(String sourceFile, String destDir) {
		try {
			// 保证文件夹路径最后是"/"或者"\"
			char lastChar = destDir.charAt(destDir.length() - 1);
			if (lastChar != '/' && lastChar != '\\') {
				destDir += File.separator;
			}
			// 根据类型，进行相应的解压缩
			String type = sourceFile.substring(sourceFile.lastIndexOf(".") + 1)
					.toLowerCase();
			if (type.equals("zip") || type.equals("ptpl")
					|| type.equals("ctpl") || type.equals("tpl")) {
				ZipUtil.unzip(sourceFile, destDir);
				return 0;
			} else if (type.equals("rar")) {
				ZipUtil.unrar(sourceFile, destDir);
				return 0;
			} else {
				throw new Exception("只支持zip和rar格式的压缩包！");
			}
		} catch (Exception ex) {
			return 1;
		}
	}

	/**
	 * 设置缩略图
	 * @param pathFile
	 * @return
	 */
	public static boolean setThumbIcon(String pathFile, int width, int height) {
		try {
			int lastIndex = pathFile.lastIndexOf("/");
			String path = pathFile.substring(0, lastIndex);
			String fileName = pathFile.substring(lastIndex + 1);
			File file = new File(path);
			if (!file.exists()) {
				file.mkdirs();
			}
			ImageUtil imageUtil = new ImageUtil();
			imageUtil.compressPic(file.getPath() + "/", file.getPath() + "/",
					fileName, fileName, width, width, false);
			return true;
		} catch (Exception e) {
			log.error("", e);
			return false;
		}
	}

	public static long writeFile(String path,String fileName,byte[] array,int len)throws Exception{
		String savePath = path+"/"+fileName;

		if(!FileUtil.exists(path))
			FileUtil.mkdirs(path);
		if (!FileUtil.exists(savePath))
		{
			OutputStream os = new FileOutputStream(savePath);
			//获得字节数组
			byte[] data = array;
			//开始写入
			os.write(data, 0, len);
			//清空缓冲区、关闭流
			os.flush();
			os.close();
		}else{
			OutputStream os = new FileOutputStream(savePath,true);
			//获得字节数组
			byte[] data = array;
			//开始写入
			os.write(data, 0, len);
			//清空缓冲区、关闭流
			os.flush();
			os.close();
		}

		File file = new File(savePath);
		return file.length();


	}

	/**
	 * 如果文件不存在，则创建一个新文件
	 * @param path 文件的路径
	 * @param fileName 文件名称
	 * @return 文件存在或创建成功返回true
	 * @throws IOException
	 */
	public static boolean createFile(String path, String fileName)
	{
		boolean creator = true;
		File myPath = new File(path, fileName);
		if (!myPath.exists())
		{
			try{
				creator = myPath.createNewFile();
			}catch(Exception ex){
				creator = false;
			}
		}
		return creator;

	}

	/**
	 * 如果目录不存在，则创建目录
	 * @param path 需要创建的目录
	 * @return 存在或创建成功返回true
	 */
	public static boolean makeDir(String path)
	{
		boolean mk = true;
		File myPath = new File(path);
		if (!myPath.exists())
		{
			mk = myPath.mkdirs();
		}
		return mk;
	}
}
